package cn.com.twoke.easyproject.config;

import cn.com.twoke.easyproject.config.version.ApiVersion;
import cn.hutool.core.lang.Opt;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.apache.commons.lang3.RandomUtils;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import java.util.HashMap;
import java.util.Map;

/**
 * 只允许在本地、开发、测试环境中运行
 */
@Configuration
@Profile({"local", "dev", "test"})
public class Openapi3SwaggerConfiguration {

    @Value("${sa-token.token-name}")
    private String tokenName;

    @Bean
    public GlobalOpenApiCustomizer orderGlobalOpenApiCustomizer() {
        return openApi -> {
            if(openApi.getPaths()!=null){
                if (openApi.getTags()!=null){
                    openApi.getTags().forEach(tag -> {
                        Map<String,Object> map=new HashMap<>();
                        map.put("x-order", RandomUtils.nextInt(0,100));
                        tag.setExtensions(map);
                    });
                }
                openApi.getPaths().forEach((api, pathItem) -> {
                    // 为所有接口添加鉴权
                    pathItem.readOperations().forEach(operation -> {
                        Opt.ofNullable(operation.getParameters()).ifPresent(parameters -> {
                            parameters.forEach(parameter -> {
                                if ("size".equals(parameter.getName())) {
                                    parameter.setDescription("每页大小, 默认值 10");
                                } else if ("current".equals(parameter.getName())) {
                                    parameter.setDescription("当前页数，默认值 1");
                                }
                            });
                            parameters.removeIf(parameter -> "total,records".contains(parameter.getName()));
                        });
                        operation.addParametersItem(new Parameter()
                                .name(tokenName)
                                .in(SecurityScheme.In.HEADER.toString())
                                .description("访问凭证，前后端分离需要使用token访问")
                        );
                        if (api.contains("{version}")) {
                            operation.addParametersItem(new Parameter()
                                    .name("version")
                                    .example("v1")
                                    .required(true)
                                    .in(SecurityScheme.In.QUERY.toString())
                                    .description("API版本号")
                            );
                        }
                    });
                });
            }
            Components components = openApi.getComponents();
            components.getSchemas().forEach((key, schema) -> {
                if (key.startsWith("IPage")) { // 分页参数
                    schema.getProperties().forEach((property, value) -> {
                        if (value instanceof IntegerSchema integerSchema) {
                            if ("size".equals(property)) {
                                integerSchema.setDescription("每页大小");
                            } else if ("pages".equals(property)) {
                                integerSchema.setDescription("总页数");
                            }  else if ("current".equals(property)) {
                                integerSchema.setDescription("当前页数");
                            }  else if ("total".equals(property)) {
                                integerSchema.setDescription("数据总条数");
                            }
                        } else if (value instanceof ArraySchema arraySchema) {
                            if ("records".equals(property)) {
                                arraySchema.setDescription("数据项");
                            }
                        }
                    });
                }
            });
        };
    }

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("EasyProject接口文档")
                        .version("v1.0.0")
                        .description("EasyProject接口文档")
                        .license(new License().name("Apache 2.0"))
                        .contact(new Contact().name("TwoKe").email("twoke945@163.com"))
                );
    }
}
